package cn.com.anypay.manager.payment.core;

import cn.com.anypay.manager.payment.dto.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 抽象支付产品模板类
 *
 * 使用模板方法模式，提供支付产品的通用逻辑实现
 * 具体的支付产品策略类继承此类并实现抽象方法
 *
 * @author AnyPay Team
 * @version 1.0
 * @since 2025-07-05
 */
public abstract class AbstractPaymentProductTemplate implements IPaymentProduct {

    protected final Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 产品配置
     */
    protected ProductConfigDTO productConfig;

    /**
     * 初始化状态
     */
    protected final AtomicBoolean initialized = new AtomicBoolean(false);

    /**
     * 处理统计计数器
     */
    protected final AtomicLong processCount = new AtomicLong(0);
    protected final AtomicLong successCount = new AtomicLong(0);
    protected final AtomicLong failureCount = new AtomicLong(0);

    /**
     * 默认版本号
     */
    protected static final String DEFAULT_VERSION = "1.0.0";

    public AbstractPaymentProductTemplate() {
    }

    public AbstractPaymentProductTemplate(ProductConfigDTO productConfig) {
        this.productConfig = productConfig;
    }

    @Override
    public String getProductVersion() {
        return DEFAULT_VERSION;
    }

    @Override
    public boolean isAvailable() {
        return initialized.get() &&
               productConfig != null &&
               productConfig.isEnabled() &&
               validateConfig(productConfig);
    }

    @Override
    public void initialize() throws PaymentProductException {
        if (initialized.get()) {
            logger.warn("Product {} is already initialized", getProductType());
            return;
        }

        try {
            logger.info("Initializing product: {}", getProductType());

            // 验证配置
            if (productConfig == null) {
                throw new PaymentProductException("INIT_ERROR",
                    "Product config is null", null, getProductType());
            }

            if (!validateConfig(productConfig)) {
                throw new PaymentProductException("CONFIG_INVALID",
                    "Product config is invalid", null, getProductType());
            }

            // 执行具体的初始化逻辑
            doInitialize();

            initialized.set(true);
            logger.debug("Product {} initialized successfully", getProductType());

        } catch (Exception e) {
            initialized.set(false);
            logger.error("Failed to initialize product: {}", getProductType(), e);
            if (e instanceof PaymentProductException) {
                throw e;
            }
            throw new PaymentProductException("INIT_ERROR",
                "Failed to initialize product", e, null, getProductType());
        }
    }

    @Override
    public void destroy() {
        if (!initialized.get()) {
            return;
        }

        try {
            logger.info("Destroying product: {}", getProductType());

            // 执行具体的销毁逻辑
            doDestroy();

            initialized.set(false);
            logger.info("Product {} destroyed successfully", getProductType());

        } catch (Exception e) {
            logger.error("Failed to destroy product: {}", getProductType(), e);
        }
    }

    @Override
    public PaymentResultDTO createPayment(PaymentRequestDTO request) throws PaymentProductException {
        if (!isAvailable()) {
            throw new PaymentProductException("PRODUCT_UNAVAILABLE",
                "Product is not available", request.getChannelId(), getProductType());
        }

        if (request == null) {
            throw new PaymentProductException("INVALID_REQUEST",
                "Payment request is null", null, getProductType());
        }

        processCount.incrementAndGet();

        try {
            logger.info("Creating payment for product: {}, orderId: {}",
                getProductType(), request.getMerchantOrderId());

            // 验证请求参数
            validatePaymentRequest(request);

            // 预处理
            preProcessPayment(request);

            // 执行具体的支付创建逻辑
            PaymentResultDTO result = doCreatePayment(request);

            // 后处理
            postProcessPayment(request, result);

            successCount.incrementAndGet();
            logger.info("Payment created successfully for product: {}, orderId: {}",
                getProductType(), request.getMerchantOrderId());

            return result;

        } catch (Exception e) {
            failureCount.incrementAndGet();
            logger.error("Failed to create payment for product: {}, orderId: {}",
                getProductType(), request.getMerchantOrderId(), e);
            if (e instanceof PaymentProductException) {
                throw e;
            }
            throw new PaymentProductException("CREATE_PAYMENT_ERROR",
                "Failed to create payment", e, request.getChannelId(), getProductType());
        }
    }

    @Override
    public QueryResultDTO queryPayment(QueryRequestDTO request) throws PaymentProductException {
        if (!isAvailable()) {
            throw new PaymentProductException("PRODUCT_UNAVAILABLE",
                "Product is not available", request.getChannelId(), getProductType());
        }

        if (request == null) {
            throw new PaymentProductException("INVALID_REQUEST",
                "Query request is null", null, getProductType());
        }

        try {
            logger.info("Querying payment for product: {}, orderId: {}",
                getProductType(), request.getMerchantOrderId());

            // 验证请求参数
            validateQueryRequest(request);

            // 执行具体的查询逻辑
            QueryResultDTO result = doQueryPayment(request);

            logger.info("Payment queried successfully for product: {}, orderId: {}",
                getProductType(), request.getMerchantOrderId());

            return result;

        } catch (Exception e) {
            logger.error("Failed to query payment for product: {}, orderId: {}",
                getProductType(), request.getMerchantOrderId(), e);
            if (e instanceof PaymentProductException) {
                throw e;
            }
            throw new PaymentProductException("QUERY_PAYMENT_ERROR",
                "Failed to query payment", e, request.getChannelId(), getProductType());
        }
    }

    @Override
    public boolean closePayment(String orderId) throws PaymentProductException {
        if (!isAvailable()) {
            throw new PaymentProductException("PRODUCT_UNAVAILABLE",
                "Product is not available", null, getProductType());
        }

        if (orderId == null || orderId.trim().isEmpty()) {
            throw new PaymentProductException("INVALID_REQUEST",
                "Order ID is null or empty", null, getProductType());
        }

        try {
            logger.info("Closing payment for product: {}, orderId: {}", getProductType(), orderId);

            // 执行具体的关闭逻辑
            boolean result = doClosePayment(orderId);

            logger.info("Payment closed successfully for product: {}, orderId: {}",
                getProductType(), orderId);

            return result;

        } catch (Exception e) {
            logger.error("Failed to close payment for product: {}, orderId: {}",
                getProductType(), orderId, e);
            if (e instanceof PaymentProductException) {
                throw e;
            }
            throw new PaymentProductException("CLOSE_PAYMENT_ERROR",
                "Failed to close payment", e, null, getProductType());
        }
    }

    @Override
    public boolean verifyCallback(String callbackData) throws PaymentProductException {
        if (!isAvailable()) {
            throw new PaymentProductException("PRODUCT_UNAVAILABLE",
                "Product is not available", null, getProductType());
        }

        if (callbackData == null || callbackData.trim().isEmpty()) {
            throw new PaymentProductException("INVALID_REQUEST",
                "Callback data is null or empty", null, getProductType());
        }

        try {
            logger.info("Verifying callback for product: {}", getProductType());

            // 执行具体的验证逻辑
            boolean result = doVerifyCallback(callbackData);

            logger.info("Callback verified successfully for product: {}", getProductType());

            return result;

        } catch (Exception e) {
            logger.error("Failed to verify callback for product: {}", getProductType(), e);
            if (e instanceof PaymentProductException) {
                throw e;
            }
            throw new PaymentProductException("VERIFY_CALLBACK_ERROR",
                "Failed to verify callback", e, null, getProductType());
        }
    }

    @Override
    public PaymentResultDTO processCallback(String callbackData) throws PaymentProductException {
        if (!isAvailable()) {
            throw new PaymentProductException("PRODUCT_UNAVAILABLE",
                "Product is not available", null, getProductType());
        }

        if (callbackData == null || callbackData.trim().isEmpty()) {
            throw new PaymentProductException("INVALID_REQUEST",
                "Callback data is null or empty", null, getProductType());
        }

        try {
            logger.info("Processing callback for product: {}", getProductType());

            // 验证回调数据
            if (!verifyCallback(callbackData)) {
                throw new PaymentProductException("CALLBACK_VERIFY_FAILED",
                    "Callback verification failed", null, getProductType());
            }

            // 执行具体的处理逻辑
            PaymentResultDTO result = doProcessCallback(callbackData);

            logger.info("Callback processed successfully for product: {}", getProductType());

            return result;

        } catch (Exception e) {
            logger.error("Failed to process callback for product: {}", getProductType(), e);
            if (e instanceof PaymentProductException) {
                throw e;
            }
            throw new PaymentProductException("PROCESS_CALLBACK_ERROR",
                "Failed to process callback", e, null, getProductType());
        }
    }

    @Override
    public boolean validateConfig(ProductConfigDTO config) {
        if (config == null) {
            return false;
        }

        try {
            return doValidateConfig(config);
        } catch (Exception e) {
            logger.error("Config validation failed for product: {}", getProductType(), e);
            return false;
        }
    }

    @Override
    public Map<String, Object> getStatistics() {
        Map<String, Object> stats = new HashMap<>();
        stats.put("productType", getProductType());
        stats.put("productName", getProductName());
        stats.put("productVersion", getProductVersion());
        stats.put("isAvailable", isAvailable());
        stats.put("processCount", processCount.get());
        stats.put("successCount", successCount.get());
        stats.put("failureCount", failureCount.get());
        stats.put("successRate", calculateSuccessRate());
        stats.put("lastUpdateTime", new Date());
        return stats;
    }

    // =============== 抽象方法，由子类实现 ===============

    /**
     * 执行初始化逻辑
     */
    protected abstract void doInitialize() throws PaymentProductException;

    /**
     * 执行销毁逻辑
     */
    protected abstract void doDestroy();

    /**
     * 执行支付创建逻辑
     */
    protected abstract PaymentResultDTO doCreatePayment(PaymentRequestDTO request) throws PaymentProductException;

    /**
     * 执行支付查询逻辑
     */
    protected abstract QueryResultDTO doQueryPayment(QueryRequestDTO request) throws PaymentProductException;

    /**
     * 执行支付关闭逻辑
     */
    protected abstract boolean doClosePayment(String orderId) throws PaymentProductException;

    /**
     * 执行回调验证逻辑
     */
    protected abstract boolean doVerifyCallback(String callbackData) throws PaymentProductException;

    /**
     * 执行回调处理逻辑
     */
    protected abstract PaymentResultDTO doProcessCallback(String callbackData) throws PaymentProductException;

    /**
     * 执行配置验证逻辑
     */
    protected abstract boolean doValidateConfig(ProductConfigDTO config);

    // =============== 钩子方法，子类可以重写 ===============

    /**
     * 验证支付请求参数
     */
    protected void validatePaymentRequest(PaymentRequestDTO request) throws PaymentProductException {
        if (request.getMerchantOrderId() == null || request.getMerchantOrderId().trim().isEmpty()) {
            throw new PaymentProductException("INVALID_REQUEST",
                "Merchant order ID is null or empty", request.getChannelId(), getProductType());
        }

        if (request.getAmount() == null || request.getAmount().compareTo(java.math.BigDecimal.ZERO) <= 0) {
            throw new PaymentProductException("INVALID_REQUEST",
                "Amount is null or invalid", request.getChannelId(), getProductType());
        }

        if (request.getPayProduct() == null || !request.getPayProduct().equals(getProductType())) {
            throw new PaymentProductException("INVALID_REQUEST",
                "Pay product type mismatch", request.getChannelId(), getProductType());
        }
    }

    /**
     * 验证查询请求参数
     */
    protected void validateQueryRequest(QueryRequestDTO request) throws PaymentProductException {
        if (request.getMerchantOrderId() == null || request.getMerchantOrderId().trim().isEmpty()) {
            throw new PaymentProductException("INVALID_REQUEST",
                "Merchant order ID is null or empty", request.getChannelId(), getProductType());
        }
    }

    /**
     * 支付预处理
     */
    protected void preProcessPayment(PaymentRequestDTO request) {
        // 默认实现为空，子类可以重写
    }

    /**
     * 支付后处理
     */
    protected void postProcessPayment(PaymentRequestDTO request, PaymentResultDTO result) {
        // 默认实现为空，子类可以重写
    }

    /**
     * 计算成功率
     */
    protected double calculateSuccessRate() {
        long total = processCount.get();
        if (total == 0) {
            return 0.0;
        }
        return (double) successCount.get() / total * 100;
    }

    // =============== Getters and Setters ===============

    public ProductConfigDTO getProductConfig() {
        return productConfig;
    }

    public void setProductConfig(ProductConfigDTO productConfig) {
        this.productConfig = productConfig;
    }

    public boolean isInitialized() {
        return initialized.get();
    }
}